grammar rongo;
/*options{
k=2;
}*/
@header {
import java.util.HashMap;
/* import org.rongo.ASTNode; */
}


@members {
/* Map variable name to Integer object holding value */
HashMap memory = new HashMap();
}

prog
	:	stat+
	;

stat
	: 	type_decl NEWLINE+ 
	|	assign NEWLINE+
	|	expr NEWLINE+
	|	io NEWLINE+	
	|	COMMENT
	;

io
	:	'print' LPAREN expr RPAREN	 {System.out.println($expr.value);}
	;	
	
type_decl returns [int value]
	:	'int:' (a=ID {memory.put($a.text, 0);} | assign) (',' (assign | b=ID {memory.put($b.text, 0);})* )*
	;

assign returns [int value]
	:	ID EQUALS e=expr {memory.put($ID.text, new Integer($e.value));}
	;

expr returns [int value]
	:	e=mexpr {$value = $e.value;}
	(	PLUS e=mexpr {$value += $e.value;}
	 |	MINUS e=mexpr {$value -= $e.value;} 
        )*
	;

mexpr returns[int value] 
	:	e=powexpr {$value = $e.value;} 
	(	TIMES e=powexpr {$value *= $e.value;}
	 |	DIV e=powexpr {$value /= $e.value;}
	 |	MOD f=powexpr {$value = $e.value \% $f.value; }
	)*
	;
powexpr returns [int value] 
	:	e=factor {$value = $e.value;}
	(	POW f=factor {$value = (int) Math.pow($e.value, $f.value);}	
	)*	
	;

factor returns[int value]
	:	LPAREN e=expr {$value = $e.value;} RPAREN
	|	e=atom {$value = $e.value;}
	;

atom returns[int value]
	:	a=INT  {$value = Integer.parseInt($a.text);}
	|	MINUS b=INT {$value = -Integer.parseInt($b.text);}
	|	ID {
        		Integer v = (Integer)memory.get($ID.text);
		        if ( v!=null ) $value = v.intValue();
		        else System.err.println("undefined variable "+$ID.text);
        	}
	;
			
WS	:	(' ' 
	| 	'\t')+ 
		{skip();}
	;
NEWLINE 
	: 	'\r\n'
	|	'\r'
	|	'\n'
	;

COMMENT:	'//' (~('\n'|'\r'|'\r\n'))*
		{skip();} 
		NEWLINE+
	;

INT	: 	('0'..'9')+;
PLUS 	:	'+';
MINUS 	:	'-';
TIMES	:	'*';
DIV		:'/';
LPAREN	:	'(';
RPAREN	:	')';
ID	:	('a'..'z'|'A'..'Z')('a'..'z'|'A'..'Z'|'0'..'9')*;
COLON	:	':';
EQUALS	:	'=';
MOD	:	'%';
POW	:	'**';